home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_200
/
283_01
/
svideo.asm
< prev
next >
Wrap
Assembly Source File
|
1988-12-15
|
30KB
|
721 lines
; SVIDEO.ASM - after Microsoft Systems Journal, Nov. 1988, p. 6
;
; *** Caution: Small Model stack bias! ***
;
; This program handles direct writes to the IBM PC video screen buffer
; located in RAM memory. Works with all 100% compatible clones, and
; correctly eliminates snow when using CGA. See the article in MSJ:
; "Building a device-independent video display I/O library in Microsoft C",
; by Jeff Prosise. Requires MASM v5.0 or MASM v5.1, per documentation.
;
; Memory model support by David C. Oshel, Ames, Iowa, Dec. 9, 1988.
; This file is essentially ASMVIDEO.ASM, modified for appropriate function
; calls and returns, and DS register management for various data objects.
;
; I've added four additional functions, all of which take a len argument,
; to Prosise's original set of three:
;
; MSJ_SetFldAttr, MSJ_DispMsgLen 12/10/88
; MSJ_MovScrBuf, MSJ_MovBufScr 12/11/88
;
; Added Wozniak's pattern fill to MSJ_SetFldAttr on 12/12/88, and figured
; out why I still had snow on a CGA (NCR PC 6300) on 12/13/88. See next.
;
; *** C A U T I O N ***
;
; It turns out that Prosise's XCHG AX,BX and STOSW pattern in the snow
; elimination code is a VERY time critical optimization. I actually had
; to read the article before I could expand on the original routines. Ouch.
; --- 12/13/88, d.c.oshel
;
.MODEL SMALL
.CODE
PUBLIC _MSJ_MovBufScr, _MSJ_MovScrBuf
PUBLIC _MSJ_SetFldAttr, _MSJ_DispMsgLen
PUBLIC _MSJ_DispString, _MSJ_DispCharAttr, _MSJ_GetCharAttr
;
; The C interface for these functions and structures looks like this:
;
;struct MSJ_VideoInfo {
; unsigned char mode;
; unsigned char rows;
; unsigned char columns;
; unsigned char ColorFlag;
; unsigned char SnowFlag;
; unsigned int BufferStart;
; unsigned int SegAddr;
;};
;
;extern struct MSJ_VideoInfo video; /* defined in CVIDEO.C */
;
;
;/* MSJ, Nov. 1988
; */
;extern int cdecl MSJ_GetCharAttr( char row, char col,
; struct MSJ_VideoInfo * sptr );
;
;/* MSJ, Nov. 1988
; */
;extern void cdecl MSJ_DispCharAttr( char ch,
; char row, char col,
; char VideoAttr,
; struct MSJ_VideoInfo * sptr );
;
;
;/* MSJ, Nov. 1988
; */
;extern void cdecl MSJ_DispString( char * msg,
; char row, char col,
; char VideoAttr,
; struct MSJ_VideoInfo * sptr );
;
;
;/* MSJ_DispMsgLen is like MSJ_DispString, but takes a length argument,
; and does not disturb screen attributes in the receiving field
; 12/10/88, d.c.oshel
; */
;extern void cdecl MSJ_DispMsgLen( char * msg,
; char row, char col,
; int len,
; struct MSJ_VideoInfo * sptr );
;
;
;/* MSJ_SetFldAttr takes a length argument and clears a field of the
; screen to the given char having the given attribute
; 12/10/88, d.c.oshel
; */
;extern void cdecl MSJ_SetFldAttr( char ch,
; char row,
; char col,
; char VideoAttr,
; int len,
; struct MSJ_VideoInfo * sptr );
;
;
;/* move count WORDS from screen to far buffer, 12/10/88, d.c.oshel
; */
;extern void cdecl MSJ_MovScrBuf( char far * buffer,
; char row,
; char col,
; int count,
; struct MSJ_VideoInfo * sptr );
;
;
;/* move count WORDS from far buffer to screen, 12/10/88, d.c.oshel
; */
;extern void cdecl MSJ_MovBufScr( char far * buffer,
; char row,
; char col,
; int count,
; struct MSJ_VideoInfo * sptr );
;
;-----------------------------------------------------------------------
; _MSJ_MovBufScr copies count words from the user's far save buffer to
; the active video buffer
; 12/10/88, d.c.oshel
;
; _MSJ_MovScrBuf copies count words from the active video buffer to
; the user's far save buffer
; 12/10/88, d.c.oshel
;-----------------------------------------------------------------------
;
; Arguments on the stack (SMALL MODEL):
;
; [bp+14] <--- struct MSJ_VideoInfo * sptr
; [bp+12] <--- int count
; [bp+10] <--- char col
; [bp+8] <--- char row
; [bp+6] <--- seg\ char far * buffer
; [bp+4] <--- ofs/
;
_MSJ_MovBufScr PROC
push bp ;save regs & establish stack frame
mov bp,sp
push si
push di
push es
push ds ;large model uses data segments anywhere
; COUNT: load CX with the number of bytes to move
;
mov cx,[bp+12] ;CX <-- count
cmp cx,1 ;we're already done if CX <= 0
jl exitmbs
; DESTINATION: set ES:DI to point to screen buffer absolute address
; note - this changes DS to video structure's segment
;
mov bx,[bp+14] ;DS:BX <-- ptr to video structure
test byte ptr [bx+4], 1 ;is video.SnowFlag clear?
pushf ;save answer for later
mov dh,[bp+8] ;DH <-- row
mov dl,[bp+10] ;DL <-- col
call AddressOf ;DI <-- screen offset
mov es,[bx+8] ;ES <-- video.SegAddr (screen segment)
; SOURCE: set DS:SI to point to user's save buffer
; note - this changes DS to user's far buffer segment
;
lds si,[bp+4] ;DS:SI <-- ptr to source
cld
popf
jnz hardway
; BEST CASE, move the string from DS:SI to ES:DI, with immediate writes
;
rep movsw ;move all immediately
jmp exitmbs
hardway: lodsw ;get char from buffer
xchg ax,bx
cli ;disable interrupts
mov dx,3DAh ;DX <- ptr to Status Register
st1: in al,dx ;if we've arrived during a
test al,1 ;horizontal blanking interval,
jnz st1 ;must wait for the start of next!
st2: in al,dx ;bit one is horizontal retrace
test al,1 ;bit three is vertical retrace
jz st2 ;if nz, horizontal blanking is NOW.
; Move up to 16 bits ONLY to the screen, taking advantage
; of the 8088's 4-byte prefetch buffer to save time (!),
; during the 7 microseconds of horizontal blanking;
; Prosise says timing is so tight we MUST use the XCHG
; instruction to get AX back, and nothing else will do.
;
; There are 200 horizontal retrace intervals per frame,
; only one vertical retrace interval per frame; i.e., 200
; lines on the screen, horizontal retrace is the zag
; following raster scan's zig, vertical retrace is the
; corner-to-corner diagonal path back to top of screen.
;
; For reference, 65 clock cycles are about 1